<style lang="scss">
  .upload-image {
    .el-upload-list--picture-card  {
      .el-upload-list__item {
        width: 183px;
        height: 183px;
      }
    }
    .el-upload-dragger {
      width: auto;
      padding: 0 10px;
    }
    &.inline {
      display: inline-block;
    }
    .picture-num {
      display: inline-block;
      transform: rotate(-45deg);
      margin: 3.5px 0 0 2px;
      color: #fff;
    }
    .el-upload-list {
      div {
        display: inline-block;
      }
    }
  }
</style>
<template>
  <div class="upload-image" :class="{'inline': inline}">
    <ul class="el-upload-list el-upload-list--picture-card pull-left">
      <Viewer ref="viewer" @inited="inited" :images="images" v-if="showImageList">
        <template slot-scope="scope">
          <li :key="index" v-for="(src, index) in scope.images" v-show="showPictureNum ? index == 0 : true" class="el-upload-list__item is-success" :style="listItemStyle">
            <img :src="src" alt="" class="el-upload-list__item-thumbnail">
            <label class="el-upload-list__item-status-label">
              <i v-if="!readonly" class="el-icon-upload-success el-icon-check"></i>
              <span v-if="readonly" class="picture-num">{{scope.images.length}}</span>
            </label>
            <i class="el-icon-close"></i><i class="el-icon-close-tip"></i>
            <span class="el-upload-list__item-actions">
              <span class="el-upload-list__item-preview" @click.prevent="showImage(index)"><i class="el-icon-zoom-in"></i></span>
              <span class="el-upload-list__item-delete" v-if="!readonly" @click.prevent="delImage(index)"><i class="el-icon-delete"></i></span>
            </span>
          </li>
        </template>
      </Viewer>
      <li v-if="showUploadBox" class="el-upload-list__item" style="border: 0px" :style="listItemStyle">
        <el-upload
          v-loading="loading"
          class="upload-base pull-left"
          :drag="drag"
          action="/zuul/ms-mongodb/file/photo/upload"
          :headers="{}"
          :data="{group: 'upload-image'}"
          :show-file-list="false"
          name="photo"
          :multiple="multiple"
          :on-success="onSuccess"
          :before-upload="beforeUpload"
          :http-request="httpRequest">
          <slot>
            <i class="el-icon-upload"></i>
            <div>将文件拖到此处，或<em>点击上传</em></div>
          </slot>
        </el-upload>
      </li>
    </ul>
    <div class="clearfix"> </div>
  </div>
</template>
<script>
import {alert, isEqual} from '@/utils'
import Emitter from '@/utils/emitter'
import upload from './ajax'
export default {
  mixins: [Emitter],
  props: {
    sizeLimit: { // 最大大小单位M
      type: Number,
      default: 10
    },
    max: {
      type: Number,
      default: 100
    },
    value: {
      type: Array,
      default() {
        return []
      }
    },
    readonly: {
      type: Boolean,
      default: false
    },
    inline: {
      type: Boolean,
      default: false
    },
    drag: {
      type: Boolean,
      default: true
    },
    showImageList: {
      type: Boolean,
      default: true
    },
    multiple: {
      type: Boolean,
      default: true
    },
    // 一定展示上传控件
    allShowUploadBox: {
      type: Boolean,
      default: false
    },
    // 展示图片数量
    showPictureNum: {
      type: Boolean,
      default: false
    },
    listItemStyle: {
      type: Object,
      default() {
        return {
          width: '183px',
          height: '183px'
        }
      }
    }
  },
  data() {
    return {
      typeAllow: ['image/jpeg', 'image/jpg', 'image/gif', 'image/png', 'image/bmp'],
      $viewer: '',
      imagesObj: [],
      loading: false
    }
  },
  computed: {
    images() {
      return this.imagesObj.map(v => '/api/ms-mongodb/file/download?fileId=' + v.fileId)
    },
    ids() {
      return this.imagesObj.map(v => v.fileId)
    },
    showUploadBox() {
      return this.allShowUploadBox ? this.allShowUploadBox : (!this.readonly && this.images.length < this.max)
    }
  },
  watch: {
    ids(val, oldVal) {
      if (isEqual(val, oldVal) && isEqual(val, this.value)) {
        return
      }
      this.$emit('input', val)
      this.$nextTick(_ => {
        this.dispatch('ElFormItem', 'el.form.change', val)
      })
    },
    value(val, oldVal) {
      if (val === oldVal) {
        return
      }
      this.initValue(val)
    }
  },
  created() {
    this.initValue(this.value)
  },
  methods: {
    onSuccess(response, file, fileList) {
      if (response && response.success) {
        if (this.multiple) {
          if (this.imagesObj.length < this.max) {
            this.imagesObj.push({fileId: response.data.fileId})
          } else {
            alert(`图片最多允许上传${this.max}张`)
            return false
          }
        } else {
          this.imagesObj = [{fileId: response.data.fileId}]
        }
      }
      this.$emit('onSuccess', response, file, fileList)
    },
    inited(viewer) {
      this.$viewer = viewer
    },
    beforeUpload(file) {
      // 进行验证
      const sizeM = file.size / 1024 / 1024
      if (sizeM > this.sizeLimit) {
        alert('文件大小过大大于：' + this.sizeLimit + 'M')
        return false
      }
      if (this.typeAllow.indexOf(file.type) < 0) {
        alert(`${file.type}文件类型不允许`)
        return false
      }
      if (this.imagesObj.length > this.max) {
        alert(`图片最多允许上传${this.max}张`)
        return false
      }
    },
    showImage(index) {
      if (this.$viewer) {
        this.$viewer.view(index)
      }
    },
    delImage(index) {
      this.imagesObj.splice(index, 1)
    },
    // 上传的方法
    httpRequest(option) {
      this.loading = true
      if (this.imagesObj.length < this.max) {
        upload(option).then(response => {
          if (response.success) {
            let name = response.data.fileName.slice(0, response.data.fileName.lastIndexOf('.'))
            this.$emit('file', {fileId: response.data.fileId, fileName: name})
          }
        }).finally(_ => {
          this.loading = false
        })
      }
    },
    initValue(val) {
      if (Array.isArray(val) && val.length) {
        this.imagesObj = val.map(v => { return {fileId: v} })
      } else {
        this.imagesObj = []
      }
    }
  }
}
</script>
